<template>
  <div :style="styles" class="map-body" v-loading="initLoading">
    <div v-show="!initStatus && !initLoading">
      <div class="text-red">初始化组件失败</div>
    </div>
    <div class="map-search-box" v-show="!isSetHeight">
      <el-input
        class="map-search-input"
        v-model="searchText"
        id="searchInput"
        placeholder="输入关键字搜索"
        clearable
      >
        <template #append>
          <el-button @click="mapSearch(false)" :icon="Search" />
        </template>
      </el-input>
    </div>
    <!-- 地图 -->
    <div class="map-box" :style="{ height: 'calc(' + mapHegiht + ' - 340px)' }">
      <div class="flex items-center">
        <div class="map-hide-btn icon icon-fangwen" @click="setHeight"></div>
        <div class="ml50 mt10 text-grey" v-show="isSetHeight">
          地图已隐藏，点击左边按钮可展示
        </div>
      </div>
      <div class="map-box-main" id="mapContainer"></div>
      <!--  -->
      <div
        class="map-select-box"
        v-if="selectedData.name"
        v-show="!isSetHeight"
      >
        <div>
          经纬度:{{ selectedData.location.lng }},{{ selectedData.location.lat }}
        </div>
        <div class="map-select-box-name">
          {{ selectedData.name }}{{ selectedData.name }}
        </div>
      </div>
    </div>

    <!--  -->
    <div class="map-address" v-loading="searchLoading" v-show="!isSetHeight">
      <template v-if="lists.length > 0">
        <div
          class="map-address-item"
          :class="index == selectedIndex ? 'is-active' : ''"
          v-for="(item, index) in lists"
          :key="index"
          @click="selectItem(item, index)"
        >
          <div>
            <div class="fw map-address-name">{{ item.name }}</div>
            <div class="text-grey">
              <span class="icon icon-location"></span>
              <div>
                <span class="mr5">{{ item.pname }}</span><span class="mr5">{{ item.cityname }}</span><span class="mr5">{{ item.adname }}</span><span class="mr5">{{ item.address }}</span>
              </div>
            </div>
          </div>
          <div class="text-default icon icon-gouxuan" v-if="index == selectedIndex"></div>
        </div>
      </template>
      <div class="search-empty" v-else><p>暂无搜索结果</p></div>
    </div>
  </div>
</template>
  <script setup lang="ts" name="ck-search-map">
import {
  onMounted,
  ref,
  getCurrentInstance,
  nextTick,
  computed,
  StyleValue,
  watch,
} from "vue";
import { Search } from "@element-plus/icons-vue";

import { storeToRefs } from "pinia";
import { useConfig } from "@/store";

const { systemInfo } = storeToRefs(useConfig());

const {
  proxy: { $utils },
} = getCurrentInstance() as any;

const props = withDefaults(
  defineProps<{
    height?: string;
    width?: string;
    center?: Array<number>;
    searchCity?: string;
    zoom?: number;
    modelValue?: string | number[] | string[]; //lng,lat || [lng,lat]
    valueType?: string;
    hideBtn?: boolean;
  }>(),
  {
    height: "700px",
    width: "600px",
    center: () => {
      return [0, 0];
    },
    searchCity: "全国",
    zoom: 14,
    modelValue: "",
    valueType: "string",
    hideBtn: true,
  }
);

const emit = defineEmits(["change", "update:modelValue"]);

const mapHegiht = ref<string>(props.height);

const mapCenter = ref<number[]>(props.center);

const mapKey = ref<string>(systemInfo.value.map?.key);

const searchCity = ref<string>(props.searchCity);

const searchCityCode = ref<string>("");

const _AMap = ref<any>();

onMounted(() => {
  $utils.getScript(
    "https://webapi.amap.com/maps?v=1.4.14&key=" +
      mapKey.value +
      "&plugin=AMap.Autocomplete,AMap.PlaceSearch,AMap.CitySearch",
    nextTick(() => {
      window!._AMapSecurityConfig = {
        securityJsCode: systemInfo.value.map?.secret,
      };
      setTimeout(() => {
        _AMap.value = window?.AMap;
        toInit();
      }, 2000);
    })
  );
});

const initLoading = ref<boolean>(true);

const initStatus = ref<boolean>(true);

const lists = ref<any>([]);

const map = ref<any>();

const toInit = () => {
  if (!_AMap.value?.Map) {
    initStatus.value = false;
    $utils.errorMsg("地图组件初始化失败");
    return false;
  }
  initStatus.value = true;
  map.value = new _AMap.value.Map("mapContainer", {
    zoom: props.zoom,
    resizeEnable: true,
  });

  initLoading.value = false;

  new _AMap.value.CitySearch().getLocalCity((status: string, result: any) => {
    if (status === "complete" && result.info === "OK") {
      var currentCenter = map.value.getCenter();
      mapCenter.value = [currentCenter.lng, currentCenter.lat];
      searchCity.value = result.city;
      searchCityCode.value = result.adcode;

      mapSearch(true);
    } else {
      $utils.errorMsg("获取当前城市地址错误");
    }
    Autocomplete();
  });

  map.value.on("dragstart", (res: { type: string }) => {
    console.log(res);
    var currentCenter = map.value.getCenter();
    mapCenter.value = [currentCenter.lng, currentCenter.lat];
    mapSearch(true);
  });
};

const Autocomplete = () => {
  _AMap.value.event.addListener(
    new _AMap.value.Autocomplete({
      city: searchCity.value,
      input: "searchInput",
    }),
    "select",
    (res: any) => {
      if (res.type == "select") {
        searchCityCode.value  = res.poi.adcode
        searchCity.value  = res.poi.adcode
        searchText.value = res.poi.name;
        mapCenter.value = [res.poi.location.lng, res.poi.location.lat];
        mapSearch();
      }
    }
  );
};

const mapSearch = (isNear: boolean = false, isAll: boolean = false) => {
  selectedIndex.value = -1;
  searchLoading.value = true;
  //构造地点查询类
  var placeSearch = new _AMap.value.PlaceSearch({
    type: "汽车服务|餐饮服务|购物服务|生活服务|体育休闲服务|医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|交通设施服务|金融保险服务|公司企业|地名地址信息",
    pageSize: 30,
    pageIndex: 1,
    extensions: 'all',
    city:props.searchCity,
    citylimit: true,
  });
  if (isNear) {
    placeSearch.searchNearBy(
      "",
      [mapCenter.value[0], mapCenter.value[1]],
      3000,
      (status: string, result: any) => {
        if (status == "complete") {
          lists.value = result.poiList.pois; //将查询到的地点赋值
        } else if (status == "error") {
          $utils.errorMsg(result);
        }
        setSearchLoading(false);
      }
    );
  } else {
    placeSearch.search(searchText.value, (status: string, result: any) => {
      if (status == "complete") {
        lists.value = result.poiList.pois; //将查询到的地点赋值
      } else if (status == "error") {
        $utils.errorMsg(result);
      }
      map.value.setCenter(mapCenter.value);
      setSearchLoading(false);
    });
  }
};

const searchText = ref<string>("");

const searchLoading = ref<boolean>(false);

const selectedIndex = ref<number | string>(-1);

const selectedData = ref<any>({});

const setSearchLoading = (v: boolean) => {
  setTimeout(() => {
    searchLoading.value = v;
  }, 300);
};

const markerItem = ref<any>();

const selectItem = (item: any, index: number) => {
  selectedIndex.value = index;
  // 清除 marker
  map.value.clearMap();
  var marker = new _AMap.value.Marker({
    icon: new _AMap.value.Icon({
      image: $utils.staticImgPath("marker_01.png", "assets"),
      size: new _AMap.value.Size(18, 30),
      imageSize: new _AMap.value.Size(18, 30),
    }),
    position: [item.location.lng, item.location.lat],
  });
  map.value.add(marker);
  map.value.setCenter([item.location.lng, item.location.lat]);
  map.value.setZoom(props.zoom);
  selectedData.value = item;
  emit("change", item);
  emit(
    "update:modelValue",
    props.valueType == "string"
      ? item.location.lng + "," + item.location.lat
      : [item.location.lng, item.location.lat]
  );
};
watch(
  () => searchText.value,
  (val, old) => {
    if (val == "" && old != "") {
      mapSearch();
    }
  },
  {
    deep: true,
  }
);

const styles = ref<any>([
  `width: ${props.width}`,
  `height: ${mapHegiht.value}`,
]);

const isSetHeight = ref<boolean>(false);

const setHeight = () => {
  if (!isSetHeight.value) {
    mapHegiht.value = `50px`;
  } else {
    mapHegiht.value = props.height;
  }
  styles.value = [`width: ${props.width}`, `height: ${mapHegiht.value}`];
  isSetHeight.value = !isSetHeight.value;
};
</script>
  <style scoped>
.map-body {
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 2px;
  position: relative;
}
.map-search-input {
  position: absolute;
  z-index: 2;
  top: 10px;
  right: 10px;
  width: 50%;
  min-width: 300px;
  background: none;
}
.map-box {
  width: 100%;
  border-bottom: 1px solid var(--el-border-color-lighter);
  position: relative;
}
.map-box-main {
  height: 100%;
  width: 100%;
}

.search-empty {
  text-align: center;
  line-height: 100px;
  color: var(--base-grey);
}

.map-address {
  height: 328px;
  overflow-y: scroll;
  margin-top: 10px;
}
.map-address-item {
  padding: 5px 10px;
  border: 1px dashed var(--el-border-color-lighter);
  margin: 5px;
  cursor: pointer;
  border-radius: 2px;
  line-height: 24px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.map-address-item:hover {
  border: 1px dashed var(--base-default);
}
.map-address-item.is-active {
  color: var(--base-default);
  background: var(--base-default-dark);
  border: 1px dashed var(--base-default);
}
.map-address-item:hover .map-address-name {
  color: var(--base-default);
}

.map-select-box {
  position: absolute;
  bottom: 10px;
  right: 10px;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 2px;
  height: 40px;
  width: 200px;
  color: #fff;
  padding: 5px 10px;
  line-height: 20px;
  font-size: 12px;
}
.map-select-box-name {
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
}
.map-hide-btn {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  height: 30px;
  line-height: 30px;
  width: 30px;
  border-radius: 30px;
  background: #fff;
  color: var(--base-grey);
  text-align: center;
  box-shadow: 0px 2px 6px 0px rgb(0 21 41 / 10%);
  cursor: pointer;
}
</style>
  